package sw6.launcher;

import java.util.HashMap;

import sw6.launcher.TableInfo.Applications;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;

/**
 * Provides info about applications installed.
 * Allows for retrieving, adding, updating and deleting application information.
 * @author SW6C
 *
 */
public class ApplicationInfoProvider extends ContentProvider {
	/** Log tag */
    private static final String tag = "GirafLauncherProvider";

    /** The content URI of the applications table */
	public static final Uri CONTENT_URI = Uri
	.parse("content://sw6.launcher.provider/applications");

	/** Database file name */
	private static final String DATABASE_NAME = "giraf_applications.db";
	
	/** Database version code */
	private static final int DATABASE_VERSION = 3;
	
	/** Table name  */
	private static final String APPLICATIONS_TABLE_NAME = "applications";
	
	/** Projection map for applications table */
	public static final HashMap<String, String> sApplicationsProjectionMap;

	/** UriMacther return code for content uri without id */
	private static final int APPLICATIONS = 1;
	
	/** UriMatcher return code for content uri with id */
	private static final int APPLICATION_ID = 2;

	/** Static UriMatcher for applications table */
	private static final UriMatcher sUriMatcher;

	/**
	 * Database helper class for creating the connection to the database.
	 * @author SW6C
	 *
	 */
	private static class DatabaseHelper extends SQLiteOpenHelper {

	    /**
	     * Constructor for creating the database connection.
	     * @param context the context to create the connection from.
	     */
		public DatabaseHelper(Context context) {
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
		}

		@Override
		public void onCreate(SQLiteDatabase db) {
			db.execSQL("CREATE TABLE " + APPLICATIONS_TABLE_NAME + " ("
					+ Applications._ID + " INTEGER PRIMARY KEY,"
					+ Applications.APPLICATION_OBJECT + " BLOB,"
					+ Applications.PACKAGE_NAME + " TEXT,"
					+ Applications.SSID_BLACKLIST + " BLOB);");

		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			Log.w(tag, "Upgrading database from version " + oldVersion + " to "
					+ newVersion + ", which will destroy all old data");
			db.execSQL("DROP TABLE IF EXISTS applications");
			onCreate(db);
		}

	}

	/** Instance of the database helper. */
	private DatabaseHelper mOpenHelper;

	@Override
	public boolean onCreate() {
		mOpenHelper = new DatabaseHelper(getContext());
		return true;
	}

	@Override
	public Cursor query(Uri uri, String[] projection, String selection,
			String[] selectionArgs, String sortOrder) {
		SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
		qb.setTables(APPLICATIONS_TABLE_NAME);

		switch (sUriMatcher.match(uri)) {
		case APPLICATIONS:
			qb.setProjectionMap(sApplicationsProjectionMap);
			break;
		case APPLICATION_ID:
			qb.setProjectionMap(sApplicationsProjectionMap);
			qb.appendWhere(Applications._ID + " ="
					+ uri.getPathSegments().get(1));
			break;
		default:
			throw new IllegalArgumentException("Unknown URI: " + uri);
		}

		String orderBy;
		if (TextUtils.isEmpty(sortOrder)) {
			orderBy = Applications.DEFAULT_SORT_ORDER;
		} else {
			orderBy = sortOrder;
		}

		SQLiteDatabase db = mOpenHelper.getReadableDatabase();
		Cursor c = qb.query(db, projection, selection, selectionArgs, null,
				null, orderBy);
		c.setNotificationUri(getContext().getContentResolver(), uri);
		return c;
	}

	@Override
	public String getType(Uri uri) {
		switch (sUriMatcher.match(uri)) {
		case APPLICATIONS:
			return Applications.CONTENT_TYPE;
		case APPLICATION_ID:
			return Applications.CONTENT_ITEM_TYPE;
		default:
			throw new IllegalArgumentException("Unknown URI: " + uri);
		}
	}

	@Override
	public Uri insert(Uri uri, ContentValues initialValues) {
		if (sUriMatcher.match(uri) != APPLICATIONS) {
			throw new IllegalArgumentException("Unknown URI: " + uri);
		}

		ContentValues values;
		if (initialValues != null) {
			values = new ContentValues(initialValues);
		} else {
			values = new ContentValues();
		}

		if (!values.containsKey(Applications.PACKAGE_NAME))
			throw new SQLException("The package name must be set!");

		if (!values.containsKey(Applications.APPLICATION_OBJECT))
			throw new SQLException("The application object must be set!");

		if (!values.containsKey(Applications.SSID_BLACKLIST)) {
			values.putNull(Applications.SSID_BLACKLIST);
		}

		SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		long rowId = db.insert(APPLICATIONS_TABLE_NAME,
				Applications.APPLICATION_OBJECT, values);
		if (rowId > 0) {
			Uri applicationUri = ContentUris.withAppendedId(
					Applications.CONTENT_URI, rowId);
			getContext().getContentResolver()
			.notifyChange(applicationUri, null);
			return applicationUri;
		}

		throw new SQLException("Failed to insert row into " + uri);
	}

	@Override
	public int delete(Uri uri, String selection, String[] selectionArgs) {
		SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		int count;

		switch (sUriMatcher.match(uri)) {
		case APPLICATIONS:
			count = db
			.delete(APPLICATIONS_TABLE_NAME, selection, selectionArgs);
			break;
		case APPLICATION_ID:
			String applicationId = uri.getPathSegments().get(1);
			count = db.delete(APPLICATIONS_TABLE_NAME, Applications._ID
					+ "="
					+ applicationId
					+ (!TextUtils.isEmpty(selection) ? " AND (" + selection
							+ ')' : ""), selectionArgs);
			break;
		default:
			throw new IllegalArgumentException("Unknown URI" + uri);
		}
		getContext().getContentResolver().notifyChange(uri, null);

		return count;
	}

	@Override
	public int update(Uri uri, ContentValues values, String selection,
			String[] selectionArgs) {
		SQLiteDatabase db = mOpenHelper.getWritableDatabase();
		int count;

		switch (sUriMatcher.match(uri)) {
		case APPLICATIONS:
			count = db.update(APPLICATIONS_TABLE_NAME, values, selection,
					selectionArgs);
			break;
		case APPLICATION_ID:
			String applicationId = uri.getPathSegments().get(1);
			count = db.update(APPLICATIONS_TABLE_NAME, values, Applications._ID
					+ "="
					+ applicationId
					+ (!TextUtils.isEmpty(selection) ? " AND (" + selection
							+ ')' : ""), selectionArgs);
			break;
		default:
			throw new IllegalArgumentException("Unknown URI" + uri);
		}
		getContext().getContentResolver().notifyChange(uri, null);

		return count;
	}

	static {
		sUriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
		sUriMatcher.addURI(TableInfo.AUTHORITY, "applications", APPLICATIONS);
		sUriMatcher.addURI(TableInfo.AUTHORITY, "applications/#",
				APPLICATION_ID);

		sApplicationsProjectionMap = new HashMap<String, String>();
		sApplicationsProjectionMap.put(Applications._ID, Applications._ID);
		sApplicationsProjectionMap.put(Applications.APPLICATION_OBJECT,
				Applications.APPLICATION_OBJECT);
		sApplicationsProjectionMap.put(Applications.SSID_BLACKLIST,
				Applications.SSID_BLACKLIST);
		sApplicationsProjectionMap.put(Applications.PACKAGE_NAME,
				Applications.PACKAGE_NAME);
	}

}